﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================
using Caffeine.Core.Metadata;
using System;
using System.Collections.Generic;
using System.IO;

namespace Caffeine.Core
{
    /// <summary>
    /// Implementers of this type supply the ability to create Caffeine Models
    /// </summary>
    public interface IModelFactory
    {
        /// <summary>
        /// Gets the dictionary containing delegates used to generate extensions for models
        /// </summary>
        IDictionary<Type, Func<ModelBase, Object>> ModelExtensions
        {
            get;
        }

        /// <summary>
        /// Gets or sets whether or not model properties are validated to be registered correctly as each model is created. If #DEBUG
        /// is specified, this will be set to true, otherwise it will be false.
        /// </summary>
        Boolean ValidateModelProperties
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets whether or not this model factory assigns each model's UniqueId property as its created.
        /// Defaults to false. Must be set to true to allow merge operations.
        /// </summary>
        Boolean AssignModelUniqueId
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the property change counter that is assigned to each model as it is created.
        /// </summary>
        IPropertyChangeCounter PropertyChangeCounter
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the exception handler for model commands
        /// </summary>
        ICommandExceptionHandler CommandExceptionHandler
        {
            get;
            set;
        }

        /// <summary>
        /// Creates a model.
        /// </summary>
        /// <typeparam name="T">Type of model to create</typeparam>
        /// <returns>A new model</returns>
        T CreateModel<T>() 
            where T : ModelBase, new();

        ModelBase CreateModel(Type modelType);

        //Discourage use
        T CreateModel<T>(ModelMetadata metadata) 
            where T : ModelBase, new();

        //Discourage use
        T CreateModel<T>(ModelMetadata metadata, ModelPropertyBase parentProperty) 
            where T : ModelBase, new();

        Byte[] SerializeModel<T>(T model, IEnumerable<Type> knownTypes)
            where T : ModelBase, new();

        void SerializeModel(ModelMetadata metadata, IEnumerable<Type> knownTypes, Stream objectGraphStream);

        T DeserializeModel<T>(Byte[] binary, IEnumerable<Type> knownTypes)
            where T : ModelBase, new();

        ModelMetadata DeserializeModel(IEnumerable<Type> knownTypes, Stream objectGraphStream);

        T CreateDeepCopy<T>(T model, IEnumerable<Type> knownTypes)
            where T : ModelBase, new();

        T CreateDeepCopy<T>(T model, IEnumerable<Type> knownTypes, Boolean assignNewUniqueId)
            where T : ModelBase, new();
    }
}

